<template>
  <div>
    <div
      v-if="showLauncher"
      class="sc-launcher"
      ref="launcher"
      :class="{ opened: isOpen }"
      :style="{ backgroundColor: colors.launcher.bg, ...dynamicPosition }"
    >
      <div
        v-if="newMessagesCount > 0 && !isOpen"
        class="sc-new-messsages-count"
      >
        {{ newMessagesCount }}
      </div>
      <i
        v-if="isOpen"
        class="el-icon-close sc-closed-icon"
        draggable="false"
        @click="close"
      ></i>
      <img
        v-else
        class="sc-open-icon"
        :src="icons.open.img"
        :alt="icons.open.name"
        draggable="false"
        @click="openAndFocus"
      />

      <ChatWindow
        ref="chatWindow"
        :message-list="messageList"
        :on-user-input-submit="onMessageWasSent"
        :participants="participants"
        :title="chatWindowTitle"
        :is-open="isOpen"
        :show-emoji="showEmoji"
        :show-file="showFile"
        :show-header="showHeader"
        :placeholder="placeholder"
        :show-typing-indicator="showTypingIndicator"
        :colors="colors"
        :always-scroll-to-bottom="alwaysScrollToBottom"
        :message-styling="messageStyling"
        :dynamicHeight="dynamicHeight"
        @close="close"
        @scrollToTop="$emit('scrollToTop')"
        @onType="$emit('onType')"
        @edit="$emit('edit', $event)"
        @remove="$emit('remove', $event)"
      >
        <template v-slot:header>
          <slot name="header"> </slot>
        </template>
        <template v-slot:user-avatar="scopedProps">
          <slot
            name="user-avatar"
            :user="scopedProps.user"
            :message="scopedProps.message"
          >
          </slot>
        </template>
        <template v-slot:text-message-body="scopedProps">
          <slot
            name="text-message-body"
            :message="scopedProps.message"
            :messageText="scopedProps.messageText"
            :messageColors="scopedProps.messageColors"
            :me="scopedProps.me"
          >
          </slot>
        </template>
        <template v-slot:system-message-body="scopedProps">
          <slot name="system-message-body" :message="scopedProps.message">
          </slot>
        </template>
        <template v-slot:text-message-toolbox="scopedProps">
          <slot
            name="text-message-toolbox"
            :message="scopedProps.message"
            :me="scopedProps.me"
          >
          </slot>
        </template>
        <template v-slot:user-input>
          <slot name="user-input"></slot>
        </template>
      </ChatWindow>
    </div>
  </div>
</template>

<script>
import store from "@/store/modules/chat";
import ChatWindow from "./ChatWindow.vue";

import OpenIcon from "@/assets/images/chat/logo-no-bg.svg";

export default {
  name: "ChatComponent",
  components: {
    ChatWindow,
  },
  props: {
    icons: {
      type: Object,
      default: function () {
        return {
          open: {
            img: OpenIcon,
            name: "default",
          },
        };
      },
    },
    showEmoji: {
      type: Boolean,
      default: false,
    },
    showEdition: {
      type: Boolean,
      default: false,
    },
    showDeletion: {
      type: Boolean,
      default: false,
    },
    isOpen: {
      type: Boolean,
      required: true,
    },
    open: {
      type: Function,
      required: true,
    },
    close: {
      type: Function,
      required: true,
    },
    showFile: {
      type: Boolean,
      default: false,
    },
    showLauncher: {
      type: Boolean,
      default: true,
    },
    showCloseButton: {
      type: Boolean,
      default: true,
    },
    showHeader: {
      type: Boolean,
      default: true,
    },
    participants: {
      type: Array,
      required: true,
    },
    title: {
      type: String,
      default: () => "",
    },
    titleImageUrl: {
      type: String,
      default: () => "",
    },
    onMessageWasSent: {
      type: Function,
      required: true,
    },
    messageList: {
      type: Array,
      default: () => [],
    },
    newMessagesCount: {
      type: Number,
      default: () => 0,
    },
    placeholder: {
      type: String,
      default: "Write a message...",
    },
    showTypingIndicator: {
      type: String,
      default: () => "",
    },
    draggle: {
      type: Boolean,
      default: true,
    },
    dynamicHeight: {
      type: Boolean,
      default: false,
    },
    colors: {
      type: Object,
      validator: (c) =>
        "header" in c &&
        "bg" in c.header &&
        "text" in c.header &&
        "launcher" in c &&
        "bg" in c.launcher &&
        "messageList" in c &&
        "bg" in c.messageList &&
        "sentMessage" in c &&
        "bg" in c.sentMessage &&
        "text" in c.sentMessage &&
        "receivedMessage" in c &&
        "bg" in c.receivedMessage &&
        "text" in c.receivedMessage &&
        "userInput" in c &&
        "bg" in c.userInput &&
        "text" in c.userInput,
      default: function () {
        return {
          header: {
            bg: "#4080ff",
            text: "#ffffff",
          },
          launcher: {
            bg: "#4080ff",
          },
          messageList: {
            bg: "#ffffff",
          },
          sentMessage: {
            bg: "#4080ff",
            text: "#ffffff",
          },
          receivedMessage: {
            bg: "#f4f7f9",
            text: "#ffffff",
          },
          userInput: {
            bg: "#f4f7f9",
            text: "#565867",
          },
        };
      },
    },
    alwaysScrollToBottom: {
      type: Boolean,
      default: () => false,
    },
    messageStyling: {
      type: Boolean,
      default: () => false,
    },
    disableUserListToggle: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      mouseDownHandler: null,
      mouseMoveHandler: null,
      mouseUpHandler: null,
      right: "25px",
      top: "calc(100vh - 100px)",
    };
  },
  computed: {
    chatWindowTitle() {
      if (this.title !== "") return this.title;

      if (this.participants.length === 0) return "You";
      if (this.participants.length > 1)
        return "You, " + this.participants[0].name + " & others";

      return "You & " + this.participants[0].name;
    },
    dynamicPosition() {
      return {
        right: this.right,
        top: this.top,
      };
    },
  },
  watch: {
    $props: {
      deep: true,
      immediate: true,
      handler(props) {
        for (const prop in props) {
          store.setState(prop, props[prop]);
        }
      },
    },
  },
  mounted() {
    if (this.draggle) this.initDraggable();
  },
  beforeDestroy() {
    this.removeDraggable();
  },
  methods: {
    openAndFocus() {
      this.open();
      this.$root.$emit("focusUserInput");
    },
    initDraggable() {
      const launcher = this.$refs.launcher;
      let isDragging = false;
      let initialRight, initialTop; // 修改为initialTop
      let offsetX, offsetY;

      const mouseDownHandler = (e) => {
        isDragging = true;
        initialRight =
          window.innerWidth - launcher.getBoundingClientRect().right;
        initialTop = launcher.getBoundingClientRect().top; // 修改为initialTop
        offsetX = e.clientX;
        offsetY = e.clientY;
      };

      const mouseMoveHandler = (e) => {
        if (this.$refs.chatWindow.isDragging) return; // 如果子组件正在拖拽，则不处理

        if (isDragging) {
          const x = e.clientX - offsetX;
          const y = e.clientY - offsetY;

          this.right = initialRight - x + "px";
          this.top = initialTop + y + "px"; // 修改为top定位
        }
      };

      const mouseUpHandler = () => {
        isDragging = false;
      };

      launcher.addEventListener("mousedown", mouseDownHandler);
      document.addEventListener("mousemove", mouseMoveHandler);
      document.addEventListener("mouseup", mouseUpHandler);

      // 存储事件处理程序，以便在卸载时移除它们
      this.mouseDownHandler = mouseDownHandler;
      this.mouseMoveHandler = mouseMoveHandler;
      this.mouseUpHandler = mouseUpHandler;
    },

    removeDraggable() {
      const launcher = this.$refs.launcher;
      launcher.removeEventListener("mousedown", this.mouseDownHandler);
      document.removeEventListener("mousemove", this.mouseMoveHandler);
      document.removeEventListener("mouseup", this.mouseUpHandler);
    },
  },
};
</script>

<style scoped>
.sc-launcher {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 80px;
  height: 80px;
  background-position: center;
  background-repeat: no-repeat;
  position: fixed;
  border-radius: 50%;
  box-shadow: none;
  transition: box-shadow 0.2s ease-in-out;
}

.sc-launcher .sc-open-icon {
  width: 35px;
  height: 35px;
  box-sizing: border-box;
  opacity: 1;
  transition: opacity 100ms ease-in-out, transform 100ms ease-in-out;
}

.sc-launcher .sc-closed-icon {
  transition: opacity 100ms ease-in-out, transform 100ms ease-in-out;
  font-size: 35px;
  color: #fff;
}

.sc-launcher.opened .sc-open-icon {
  transform: rotate(-90deg);
  opacity: 1;
}

.sc-launcher.opened .sc-closed-icon {
  transform: rotate(-90deg);
  opacity: 1;
}

.sc-launcher.opened:before {
  box-shadow: 0px 0px 400px 250px rgba(148, 149, 150, 0.2);
}

.sc-launcher:hover {
  box-shadow: 0 0px 27px 1.5px rgba(0, 0, 0, 0.2);
}

.sc-new-messsages-count {
  position: absolute;
  top: -3px;
  left: 41px;
  display: flex;
  justify-content: center;
  flex-direction: column;
  border-radius: 50%;
  width: 22px;
  height: 22px;
  background: #ff4646;
  color: white;
  text-align: center;
  margin: auto;
  font-size: 12px;
  font-weight: 500;
}
</style>
